(ns amsi.common.worker
  (:require [amsi.common.logging :as logger])
  (:import (java.util.concurrent LinkedBlockingQueue Executors ExecutorService)))

;This code is based on https://github.com/getwoven/work
;getwoven/work has not posibility to submit task into pool so i decided
;to create my own worker based on some ideas from getwoven/work.

(defn create-pool
  "Creates thread pool with defined size"
  [size]
  (Executors/newFixedThreadPool size))

(defn create-queue
  "Creates blocking queue"
  []
  (LinkedBlockingQueue.))

(defn consume-task
  "Takes a task from blocking queue and processes it. A aueue contains tasks. F is fn for processing tasks"
  [queue f args]
  (loop[]
      (logger/log "waits for a task")
      (let [task (.take @queue)]
        (logger/log "gets task")
        (f task args))   
    (recur)))

(defn add-consume-task
  "Adds task into pool"
  [^ExecutorService pool ^Runnable runnable]  
  (.submit pool runnable))

(defn start-workers
  "Starts workers for processing tasks from the queue. The queue contains tasks. Size is number of workers. F is fn that processes task"
  [queue size f args]
    (let[pool (create-pool size)]
    (doseq[i (range size)]
      (add-consume-task pool #(consume-task queue f args)))))



